package org.example.springboot.util;


import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.example.springboot.entity.User;
import org.example.springboot.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Date;

@Component
public class JwtTokenUtils {
    private static UserService staticUserService;
    @Resource
    private UserService userService;
    public static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtils.class);
    
    @PostConstruct
    public void setUserService() {
        staticUserService = userService;
    }
    
    /**
     * 生成JWT Token
     * @param userId 用户ID
     * @param sign 签名密钥（通常是用户密码）
     * @return JWT Token字符串
     */
    public static String genToken(String userId, String sign) {
        return JWT.create()
                .withAudience(userId)  // 将 userId 保存到 token 里面，作为载荷
                .withExpiresAt(DateUtil.offsetHour(new Date(), 2))  // 2小时后token过期
                .sign(Algorithm.HMAC256(sign));  // 以 password 作为 token 的密钥
    }
    
    /**
     * 从请求中获取当前登录用户信息
     * @return 当前登录用户，如果未登录或token无效则返回null
     */
    public static User getCurrentUser() {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes == null) {
                LOGGER.error("获取当前请求上下文失败");
                return null;
            }
            
            HttpServletRequest request = attributes.getRequest();
            String token = request.getHeader("token");
            
            // 如果请求头中没有token，再尝试从请求参数中获取
            if (StringUtils.isBlank(token)) {
                token = request.getParameter("token");
            }
            
            // 如果token为空，则返回null
            if (StringUtils.isBlank(token)) {
                LOGGER.warn("获取token失败，token为空");
                return null;
            }
            
            // 解析token中的用户ID
            String userId;
            try {
                DecodedJWT jwt = JWT.decode(token);
                if (jwt.getAudience() == null || jwt.getAudience().isEmpty()) {
                    LOGGER.error("token中不包含用户ID信息");
                    return null;
                }
                userId = jwt.getAudience().get(0);
            } catch (JWTDecodeException e) {
                LOGGER.error("解析token失败，token可能已损坏: {}", token, e);
                return null;
            }
            
            // 检查token是否已过期
            try {
                DecodedJWT jwt = JWT.decode(token);
                Date expiresAt = jwt.getExpiresAt();
                if (expiresAt != null && expiresAt.before(new Date())) {
                    LOGGER.warn("token已过期: {}", token);
                    return null;
                }
            } catch (Exception e) {
                LOGGER.error("检查token过期失败: {}", token, e);
                return null;
            }
            
            // 根据用户ID获取用户信息
            if (StringUtils.isBlank(userId)) {
                LOGGER.error("从token中获取的用户ID为空");
                return null;
            }
            
            Long userIdLong;
            try {
                userIdLong = Long.valueOf(userId);
            } catch (NumberFormatException e) {
                LOGGER.error("从token中获取的用户ID无效: {}", userId, e);
                return null;
            }
            
            // 获取用户信息
            return staticUserService.getUserById(userIdLong);
            
        } catch (Exception e) {
            LOGGER.error("获取当前用户信息失败", e);
            return null;
        }
    }
    
    /**
     * 验证token是否有效
     * @param token JWT token
     * @param sign 签名密钥（通常是用户密码）
     * @return 是否有效
     */
    public static boolean verifyToken(String token, String sign) {
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(sign)).build();
            verifier.verify(token);
            return true;
        } catch (JWTVerificationException e) {
            LOGGER.error("token验证失败: {}", token, e);
            return false;
        }
    }
}
